home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
general
/
viewers
/
polyview
/
polyvw31.lha
/
Polyview3.1
/
new
/
pvdraw.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-23
|
81KB
|
2,888 lines
/*****************************************************************************
* NCSA Polyview 3.0 *
* *
* Version 3 changes and additions by Marc Andreessen. *
* Version 2 by Brian Calvert. *
* *
* Software Development Group *
* National Center for Supercomputing Applications *
* University of Illinois at Urbana-Champaign *
* *
* This is BETA release software. As such it may contain software bugs and *
* exhibit inconsistencies. *
* *
* Please send bug reports to polyview@ncsa.uiuc.edu. *
* *
* Copyright (c) 1992 The Board of Trustees of the University of Illinois. *
* *
* Permission to use, copy, and modify this software and its *
* documentation for educational, research, and non-profit purposes is *
* hereby granted, provided that the above copyright notice, the original *
* authors names, and this permission notice appear in all such copies. *
* Any distribution of this software requires the explicit and written *
* authorization of the authors. *
* *
* The University of Illinois makes no representations about the *
* suitability of this software for any purpose. It is provided "as is" *
* without warranty of any kind. *
*****************************************************************************/
/* $Header: /usr3/people/gbourhis/pv3/new/RCS/pvdraw.c,v 1.3 92/09/30 18:46:20 marca Exp $ */
#ifdef RCSLOG
$Log: pvdraw.c,v $
* Revision 1.3 92/09/30 18:46:20 marca
* Better checking for single-color palette.
*
* Revision 1.2 1992/09/19 03:43:08 marca
* Made picked-vertex jack bigger.
*
* Revision 1.1 1992/09/18 10:55:26 marca
* Initial revision
*
#endif
#include "pv.h"
#ifdef __sgi
#include <gl/sphere.h>
#endif /* __sgi */
#ifdef _IBMR2
#include "/usr/lpp/GL/utilities/inc/sphere.h"
#endif /* _IBMR2 */
static float nn[3];
#define PI 3.1415926
/* This function loads local array nn with the normal, after
computing it and normalizing. */
static void find_normal (float p1[3], float p2[3], float p3[3])
{
static float t1[3], t2[3], temp;
t1[0] = p2[0] - p1[0];
t1[1] = p2[1] - p1[1];
t1[2] = p2[2] - p1[2];
t2[0] = p2[0] - p3[0];
t2[1] = p2[1] - p3[1];
t2[2] = p2[2] - p3[2];
nn[0]= t1[1] * t2[2] - t2[1] * t1[2];
nn[1]= t1[2] * t2[0] - t2[2] * t1[0];
nn[2]= t1[0] * t2[1] - t2[0] * t1[1];
temp = 1.0 / sqrt((nn[0] * nn[0]) + (nn[1] * nn[1]) + (nn[2] * nn[2]));
nn[0] *= temp;
nn[1] *= temp;
nn[2] *= temp;
return;
}
/* Grab zbuffer values for the first time in the program and
store them in the global state. Also figure out what values
we should use for drawing polygons in outlined polygon mode
so the outlines actually !%#@$%#$@!!%#$@ show up. */
#define ZBUF_COMPRESS /* 0x2ff */ 0x10f
void init_zbuffer (void)
{
/* Set up Zbuffer values. */
gstate->zmin = getgdesc (GD_ZMIN);
gstate->zmax = getgdesc (GD_ZMAX);
/* Figure out compressed values for Zbuffer. */
if (gstate->zmin > gstate->zmax)
{
/* reduce zmin, increase zmax */
gstate->zmin_comp = gstate->zmin - ZBUF_COMPRESS;
gstate->zmax_comp = gstate->zmax + ZBUF_COMPRESS;
}
else
{
/* increase zmin, reduce zmax */
gstate->zmin_comp = gstate->zmin + ZBUF_COMPRESS;
gstate->zmax_comp = gstate->zmax - ZBUF_COMPRESS;
}
return;
}
/* ------------------------------------------------------------------------ */
/* -------------------------- SQUEEZED Z-BUFFER --------------------------- */
/* ------------------------------------------------------------------------ */
static long zmin_comp, zmax_comp;
/* This routine loads local static variables zmin_comp and zmax_comp
with appropriate values for a given window; thereafter, a call to
set_squeezed_zbuffer will to lsetdepth with those values. */
void grok_squeezed_zbuffer (state_t *state, window_t *win)
{
float zmult, zexp;
long zfactor;
zmult = WIN_SFROM(win)[RHO] / WIN_MAXWIDTH(win);
zexp = exp(zmult);
zfactor = (long)((float)ZBUF_COMPRESS * zexp);
if (zmult > 1.02)
zfactor *= zexp * 0.6;
if (zmult > 1.2)
zfactor *= zexp;
if (zmult < 0.8)
zfactor /= zmult;
/* Figure out compressed values for Zbuffer. */
if (state->zmin > state->zmax)
{
/* reduce zmin, increase zmax */
zmin_comp = state->zmin - zfactor;
zmax_comp = state->zmax + zfactor;
}
else
{
/* increase zmin, reduce zmax */
zmin_comp = state->zmin + zfactor;
zmax_comp = state->zmax - zfactor;
}
return;
}
/* This routine does an lsetdepth to accommodate a squeezed zbuffer,
with the particular squeeze values having been determined by
a call to grok_squeezed_zbuffer above. */
void set_squeezed_zbuffer (void)
{
#if 0
lsetdepth (gstate->zmax_comp, gstate->zmin_comp);
#else
lsetdepth (zmax_comp, zmin_comp);
#endif
return;
}
int redraw_windows(state_t *state)
{
window_t *win;
polyview_t *pv;
int status;
/* Initialize status flag. If any errors occurred during redraws, */
/* will tell us. */
status = ST_OKAY;
/* Redraw every window that has its please_redraw flag set to TRUE. */
for (win = state->windows; win != NULL; win = win->next)
{
if ((win->please_redraw == TRUE) &&
(win->redraw_fn != NULL))
{
if (win->type == POLYVIEW)
{
/* Focus GL on this window. */
pv = (polyview_t *)WIN_IMAGE(win);
XmxWinset (pv->drawing_volume);
/* Figure out the center of the window. */
win->cx = pv->dv_width / 2;
win->cy = pv->dv_height / 2;
/* Reset the redraw request flag and call the */
/* redraw function, checking its return value. */
win->please_redraw = FALSE;
win->animated = FALSE;
if ((*win->redraw_fn)(state, win) != ST_OKAY)
status = ST_ERROR;
/* If the window is continuously writing out raster */
/* image, write one out now. */
if (IsRasterContinuous(win))
WriteRaster(state, win, WIN_RASTERNAME(win));
if (IsRasterBlastContinuous(win))
WriteRasterOverDTM(state, win);
/* Inform other windows that this window has redrawn. */
broadcast_msg
(state, win, MSG_REDRAW, state->active_windows);
}
else if (win->type == PALETTE)
{
/* We can't XmxWinset here because the wid is
stored local to pvpal.c. */
win->please_redraw = FALSE;
if ((*win->redraw_fn)(state, win) != ST_OKAY)
status = ST_ERROR;
broadcast_msg
(state, win, MSG_REDRAW, state->active_windows);
}
else
{
/* this is a window that doesn't need to be redrawn */
win->please_redraw = FALSE;
}
}
}
return status;
}
int set_redraw(state_t *state, window_t *win)
{
/* A NULL window pointer is an error. */
assert (win != NULL);
/* Reset the window's redraw request flag. The next time the process */
/* events routine exists it will redraw the windows. */
win->please_redraw = TRUE;
return ST_OKAY;
}
/* SetOpacity sets the system to draw polygons at the specified alpha */
/* level, where alpha is a floating point number in the range [0, 1]. */
/* On some systems this is implemented using patterns, on others using */
/* alpha buffering; currently we use only patterns. */
void SetOpacity(float alpha)
{
/* Use a pattern to approximate the transparency level. An */
/* alpha level of 1.0 is a special case. */
if ((alpha >= 0.0) && (alpha <= 1.00))
{
if (FEQ (alpha, 1.0))
setpattern(0);
else
setpattern(1 + (short)(alpha * 17));
}
else
setpattern (0);
return;
}
/* Draw the small axes for a pick selection. */
void DrawJack(float (*p)[DIMS], float off)
{
float x = (*p)[X];
float y = (*p)[Y];
float z = (*p)[Z];
linewidth (2);
bgnline();
v3f(p3f(x-off, y, z));
v3f(p3f(x+off, y, z));
endline();
bgnline();
v3f(p3f(x, y-off, z));
v3f(p3f(x, y+off, z));
endline();
bgnline();
v3f(p3f(x, y, z-off));
v3f(p3f(x, y, z+off));
endline();
linewidth (1);
return;
}
int draw_grid (state_t *state, window_t *win, object_t *obj, objinfo_t *info,
int plane)
{
int i, j;
float xinc, yinc, zinc;
float xmin, ymin, zmin;
float xmax, ymax, zmax;
float vv[3];
float mwoff, xoff, yoff, zoff;
if (plane != 0)
{
/* Get the minimal x, y, z values and initialize the */
/* incremental values to zero. */
mwoff = WIN_MAXWIDTH(win) / 200.0;
xmin = WIN_STATS(win,PX).min - mwoff;
ymin = WIN_STATS(win,PY).min - mwoff;
zmin = WIN_STATS(win,PZ).min - mwoff;
xmax = WIN_STATS(win,PX).max + mwoff;
ymax = WIN_STATS(win,PY).max + mwoff;
zmax = WIN_STATS(win,PZ).max + mwoff;
xinc = yinc = zinc = 0.0;
/* Set the incremental values if the dimension is mentioned */
/* in the plane. */
if (plane & (GRIDXY | GRIDXZ))
{
xinc = (xmax - xmin) * 0.1;
xoff = (xmax - xmin) * 0.01;
}
if (plane & (GRIDXY | GRIDYZ))
{
yinc = (ymax - ymin) * 0.1;
yoff = (ymax - ymin) * 0.01;
}
if (plane & (GRIDXZ | GRIDYZ))
{
zinc = (zmax - zmin) * 0.1;
zoff = (zmax - zmin) * 0.01;
}
SetOpacity (0.3);
cpack(FOREGROUND);
if (plane & GRIDXY)
{
for (i = 0; i < 10; i++) /* X */
for (j = 0; j < 10; j++) /* Y */
{
bgnpolygon();
vv[X] = xmin + ((float)i * xinc) + xoff;
vv[Y] = ymin + ((float)j * yinc) + yoff;
vv[Z] = zmin;
v3f (vv);
vv[X] = xmin + ((float)(i + 1) * xinc) - xoff;
v3f (vv);
vv[Y] = ymin + ((float)(j + 1) * yinc) - yoff;
v3f (vv);
vv[X] = xmin + ((float)i * xinc) + xoff;
v3f (vv);
endpolygon ();
}
}
if (plane & GRIDXZ)
{
for (i = 0; i < 10; i++) /* X */
for (j = 0; j < 10; j++) /* Z */
{
bgnpolygon();
vv[X] = xmin + ((float)i * xinc) + xoff;
vv[Y] = ymin;
vv[Z] = zmin + ((float)j * zinc) + zoff;
v3f (vv);
vv[X] = xmin + ((float)(i + 1) * xinc) - xoff;
v3f (vv);
vv[Z] = zmin + ((float)(j + 1) * zinc) - zoff;
v3f (vv);
vv[X] = xmin + ((float)i * xinc) + xoff;
v3f (vv);
endpolygon ();
}
}
if (plane & GRIDYZ)
{
for (i = 0; i < 10; i++) /* Z */
for (j = 0; j < 10; j++) /* Y */
{
bgnpolygon();
vv[X] = xmin;
vv[Y] = ymin + ((float)j * yinc) + yoff;
vv[Z] = zmin + ((float)i * zinc) + zoff;
v3f (vv);
vv[Z] = zmin + ((float)(i + 1) * zinc) - zoff;
v3f (vv);
vv[Y] = ymin + ((float)(j + 1) * yinc) - yoff;
v3f (vv);
vv[Z] = zmin + ((float)i * zinc) + zoff;
v3f (vv);
endpolygon ();
}
}
SetOpacity (1.0);
if (plane & GRIDXY)
{
for (i = 0; i < 10; i++) /* X */
for (j = 0; j < 10; j++) /* Y */
{
bgnclosedline();
vv[X] = xmin + ((float)i * xinc) + xoff;
vv[Y] = ymin + ((float)j * yinc) + yoff;
vv[Z] = zmin;
v3f (vv);
vv[X] = xmin + ((float)(i + 1) * xinc) - xoff;
v3f (vv);
vv[Y] = ymin + ((float)(j + 1) * yinc) - yoff;
v3f (vv);
vv[X] = xmin + ((float)i * xinc) + xoff;
v3f (vv);
endclosedline ();
}
}
if (plane & GRIDXZ)
{
for (i = 0; i < 10; i++) /* X */
for (j = 0; j < 10; j++) /* Z */
{
bgnclosedline();
vv[X] = xmin + ((float)i * xinc) + xoff;
vv[Y] = ymin;
vv[Z] = zmin + ((float)j * zinc) + zoff;
v3f (vv);
vv[X] = xmin + ((float)(i + 1) * xinc) - xoff;
v3f (vv);
vv[Z] = zmin + ((float)(j + 1) * zinc) - zoff;
v3f (vv);
vv[X] = xmin + ((float)i * xinc) + xoff;
v3f (vv);
endclosedline ();
}
}
if (plane & GRIDYZ)
{
for (i = 0; i < 10; i++) /* Z */
for (j = 0; j < 10; j++) /* Y */
{
bgnclosedline();
vv[X] = xmin;
vv[Y] = ymin + ((float)j * yinc) + yoff;
vv[Z] = zmin + ((float)i * zinc) + zoff;
v3f (vv);
vv[Z] = zmin + ((float)(i + 1) * zinc) - zoff;
v3f (vv);
vv[Y] = ymin + ((float)(j + 1) * yinc) - yoff;
v3f (vv);
vv[Z] = zmin + ((float)i * zinc) + zoff;
v3f (vv);
endclosedline ();
}
}
}
return ST_OKAY;
}
int draw_scatter (state_t *state, window_t *win, object_t *obj, int (*fn)(),
objinfo_t *info, int plane)
{
float xmin, ymin, zmin;
float mwoff;
Vdata_t *vcolor;
int light;
if (plane != 0)
{
/* Get the minimal x, y, z values and initialize the */
/* incremental values to zero. */
mwoff = WIN_MAXWIDTH(win) / 200.0;
xmin = WIN_STATS(win,PX).min - mwoff;
ymin = WIN_STATS(win,PY).min - mwoff;
zmin = WIN_STATS(win,PZ).min - mwoff;
/* Check to see which plane the data are to be drawn in. */
/* Scale them appropriately. */
pushmatrix();
if (plane == SCATXY)
{
translate(0.0, 0.0, zmin);
scale(1.0, 1.0, 0.0);
}
if (plane == SCATXZ)
{
translate(0.0, ymin, 0.0);
scale(1.0, 0.0, 1.0);
}
if (plane == SCATYZ)
{
translate(xmin, 0.0, 0.0);
scale(0.0, 1.0, 1.0);
}
/* Draw the data in black and white. */
/* This is very very very cheesy. */
vcolor = OBJ_VDATA(obj,VCOLOR);
OBJ_VDATA(obj,VCOLOR) = NULL;
/* Turn lighting off. */
light = WIN_LIGHT(win);
WIN_LIGHT(win) = 0;
SetOpacity (0.6);
/* If we're drawing outlined faces or hidden edges, shadows should
only be faces; otherwise we draw shadows same as objects. */
if (fn == draw_outlined_faces || fn == draw_hidden_edges)
draw_faces (state, win, obj, info);
else
(*fn)(state, win, obj, info);
SetOpacity (1.0);
OBJ_VDATA(obj,VCOLOR) = vcolor;
WIN_LIGHT(win) = light;
popmatrix();
}
return ST_OKAY;
}
int draw_axis (state_t *state, window_t *win, float start[DIMS],
float end[DIMS], int axis)
{
int i;
float range, incr, tic_start[DIMS], tic_end[DIMS], mwoff;
double mag;
char value[MAXNAMELEN];
/* Decide which axis is being drawn here. */
mwoff = WIN_MAXWIDTH(win) / 200.0;
for (i = X; i < DIMS; i++)
{
/* Copy the value of the axis to the tic arrays. */
tic_start[i] = start[i];
tic_end[i] = start[i];
if (i != axis)
{
/* The non-axis values should be adjusted by a */
/* fraction of the max width to produce tics. */
tic_start[i] -= mwoff;
tic_end[i] += mwoff;
/* Only modify the first dimension encountered. */
mwoff = 0.0;
}
}
/* Get the range of values to be have tic marks drawn over. */
range = end[axis] - start[axis];
mag = floor(log10(range)+0.5);
incr = 2.0 * (float) pow((double) 10.0, mag - 1.0);
/* Draw the tic marks. */
cpack(FOREGROUND);
do
{
tic_start[axis] += incr;
tic_end[axis] += incr;
bgnline();
v3f(tic_start);
v3f(tic_end);
endline();
}
while (tic_start[axis] < end[axis]);
/* Calculate the final position. */
for (i = X; i < DIMS; i++)
end[i] = (tic_start[i]+tic_end[i])/2.0;
/* Draw the axis. */
linewidth(2);
bgnline();
v3f(start);
v3f(end);
endline();
linewidth(1);
/* Label the maximum value. */
cmov(end[X], end[Y], end[Z]);
sprintf(value, "%4g", end[axis]);
charstr(value);
return ST_OKAY;
}
int draw_axes (state_t *state, window_t *win, object_t *obj, objinfo_t *info,
int style)
{
if (style & AXESLARGE)
{
float corner[4][DIMS];
stats_t *stats;
stats = win->stats[0];
/* Assign coordinates to the corners of the axes. */
corner[0][X] = stats[PX].min;
corner[0][Y] = stats[PY].min;
corner[0][Z] = stats[PZ].min;
corner[1][X] = stats[PX].max;
corner[1][Y] = stats[PY].min;
corner[1][Z] = stats[PZ].min;
corner[2][X] = stats[PX].min;
corner[2][Y] = stats[PY].max;
corner[2][Z] = stats[PZ].min;
corner[3][X] = stats[PX].min;
corner[3][Y] = stats[PY].min;
corner[3][Z] = stats[PZ].max;
/* Draw the axes */
cpack(FOREGROUND);
draw_axis(state, win, corner[0], corner[1], X);
draw_axis(state, win, corner[0], corner[2], Y);
draw_axis(state, win, corner[0], corner[3], Z);
}
if (style & AXESSMALL)
{
static Matrix ident = {
{1.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0},
{0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 1.0}
}, m;
static float vv[3];
mmode (MPROJECTION);
getmatrix (m);
mmode (MVIEWING);
pushmatrix();
pushviewport();
zbuffer(FALSE);
viewport(10, 60, 10, 60);
SetOpacity (1.0);
cpack(0xffffff);
loadmatrix (ident);
ortho(-1.1,1.1, -1.1,1.1, -1.1,1.1);
rot(90.0-WIN_SFROM(win)[PHI]*180.0/PI,'x');
rot(-90.0-WIN_SFROM(win)[THETA]*180.0/PI,'y');
rot(-90.0, 'x');
bgnline();
vv[0] = 0.7; vv[1] = 0.0; vv[2] = 0.0;
v3f (vv);
vv[0] = 0.0;
v3f (vv);
vv[1] = 0.7;
v3f (vv);
endline();
bgnline();
vv[0] = vv[1] = vv[2] = 0.0;
v3f (vv);
vv[2] = 0.7;
v3f (vv);
endline();
/* Label the axes. */
cmov(0.8, 0.0, 0.0);
charstr("x");
cmov(0.0, 0.8, 0.0);
charstr("y");
cmov(0.0, 0.0, 0.8);
charstr("z");
zbuffer(TRUE);
popviewport();
popmatrix();
mmode (MPROJECTION);
loadmatrix (m);
mmode (MVIEWING);
}
return ST_OKAY;
}
int draw_box_style (state_t *state, window_t *win, stats_t *stats, long style)
{
if (style & (BOXWIRE | BOXSHADED | BOXSELECTED))
{
float mwoff;
float corner[8][DIMS];
mwoff = win->max_width / 200.0;
corner[0][PX] = stats[PX].min - mwoff;
corner[0][PY] = stats[PY].min - mwoff;
corner[0][PZ] = stats[PZ].min - mwoff;
corner[1][PX] = stats[PX].max + mwoff;
corner[1][PY] = stats[PY].min - mwoff;
corner[1][PZ] = stats[PZ].min - mwoff;
corner[2][PX] = stats[PX].max + mwoff;
corner[2][PY] = stats[PY].max + mwoff;
corner[2][PZ] = stats[PZ].min - mwoff;
corner[3][PX] = stats[PX].min - mwoff;
corner[3][PY] = stats[PY].max + mwoff;
corner[3][PZ] = stats[PZ].min - mwoff;
corner[4][PX] = stats[PX].min - mwoff;
corner[4][PY] = stats[PY].min - mwoff;
corner[4][PZ] = stats[PZ].max + mwoff;
corner[5][PX] = stats[PX].max + mwoff;
corner[5][PY] = stats[PY].min - mwoff;
corner[5][PZ] = stats[PZ].max + mwoff;
corner[6][PX] = stats[PX].max + mwoff;
corner[6][PY] = stats[PY].max + mwoff;
corner[6][PZ] = stats[PZ].max + mwoff;
corner[7][PX] = stats[PX].min - mwoff;
corner[7][PY] = stats[PY].max + mwoff;
corner[7][PZ] = stats[PZ].max + mwoff;
/* BOXSHADED */
if (style & BOXSHADED)
{
backface(TRUE);
SetOpacity(0.1);
cpack(FOREGROUND);
bgnpolygon();
v3f(corner[0]);
v3f(corner[1]);
v3f(corner[2]);
v3f(corner[3]);
endpolygon();
bgnpolygon();
v3f(corner[7]);
v3f(corner[6]);
v3f(corner[5]);
v3f(corner[4]);
endpolygon();
bgnpolygon();
v3f(corner[4]);
v3f(corner[5]);
v3f(corner[1]);
v3f(corner[0]);
endpolygon();
bgnpolygon();
v3f(corner[5]);
v3f(corner[6]);
v3f(corner[2]);
v3f(corner[1]);
endpolygon();
bgnpolygon();
v3f(corner[6]);
v3f(corner[7]);
v3f(corner[3]);
v3f(corner[2]);
endpolygon();
bgnpolygon();
v3f(corner[3]);
v3f(corner[7]);
v3f(corner[4]);
v3f(corner[0]);
endpolygon();
SetOpacity(1.0);
backface(FALSE);
}
/* BOXWIRE */
if (style & BOXWIRE)
{
cpack(FOREGROUND);
bgnline();
v3f(corner[0]);
v3f(corner[1]);
v3f(corner[2]);
v3f(corner[3]);
v3f(corner[0]);
v3f(corner[4]);
v3f(corner[5]);
v3f(corner[6]);
v3f(corner[7]);
v3f(corner[4]);
endline();
bgnline();
v3f(corner[1]);
v3f(corner[5]);
endline();
bgnline();
v3f(corner[2]);
v3f(corner[6]);
endline();
bgnline();
v3f(corner[3]);
v3f(corner[7]);
endline();
}
/* BOXSELECTED */
if (style & BOXSELECTED)
{
SetOpacity(0.2);
cpack(FOREGROUND);
bgnpolygon();
v3f(corner[0]);
v3f(corner[1]);
v3f(corner[2]);
v3f(corner[3]);
endpolygon();
bgnpolygon();
v3f(corner[7]);
v3f(corner[6]);
v3f(corner[5]);
v3f(corner[4]);
endpolygon();
bgnpolygon();
v3f(corner[4]);
v3f(corner[5]);
v3f(corner[1]);
v3f(corner[0]);
endpolygon();
bgnpolygon();
v3f(corner[5]);
v3f(corner[6]);
v3f(corner[2]);
v3f(corner[1]);
endpolygon();
bgnpolygon();
v3f(corner[6]);
v3f(corner[7]);
v3f(corner[3]);
v3f(corner[2]);
endpolygon();
bgnpolygon();
v3f(corner[3]);
v3f(corner[7]);
v3f(corner[4]);
v3f(corner[0]);
endpolygon();
SetOpacity(1.0);
}
}
return ST_OKAY;
}
int draw_box (state_t *state, window_t *win, object_t *obj, objinfo_t *info)
{
return draw_box_style(state, win, obj->stats[0], BOXSELECTED | BOXWIRE);
}
int draw_obj_recurs (state_t *state, window_t *win, object_t *obj,
objinfo_t *info)
{
objinfo_t local_info;
object_t *child;
/* If we don't need to draw this object tree, then return. */
if (obj->type & INACTIVE)
return ST_OKAY;
/* Save the current transformation matrix context, since update_info */
/* may change it and the recursive drawing steps will want to use */
/* it. */
pushmatrix();
pushattributes();
/* Process the new attributes and transformations to develop a new */
/* local info block. Update only those fields that have new values. */
update_info(state, info, obj->info, &local_info);
/* Using this information, either draw the object or decompose it */
/* further. */
if (obj->type & ATOM)
{
/* Go ahead and draw objects using the currently active draw */
/* function */
if ((win->use_fastdraw) && (WIN_FASTDRAW_FN(win) != NULL))
WIN_FASTDRAW(win)(state, win, obj, info);
else
{
if (local_info.draw_fn != NULL)
(*local_info.draw_fn)(state, win, obj, info);
}
}
else if (obj->type & OBJECT)
{
/* Recursively examine all the objects in the group. */
for (child = obj->u.grp.children; child != NULL;
child = child->sibling)
{
if (draw_obj_recurs(state, win, child, &local_info) != ST_OKAY)
{
popattributes();
popmatrix();
return ST_ERROR;
}
}
}
else
{
bprintf
(state, "[draw_obj_recurs] SYSTEM ERROR: Object type not defined.\n");
popattributes();
popmatrix();
return ST_ERROR;
}
/* Draw any overlays that are requested for this object. */
/* FOCUS POINT */
if (local_info.hereonly.value & FOCUSPOINT)
{
float cx, cy, cz;
float size;
/* Get the center of the FOCUSPOINT "jack" and choose a size */
/* for it. */
cx = WIN_AT(win)[X];
cy = WIN_AT(win)[Y];
cz = WIN_AT(win)[Z];
size = WIN_MAXWIDTH(win) / 200.0;
cpack(FOREGROUND);
/* Draw x-axis arm. */
bgnline();
v3f(p3f(cx-size, cy, cz));
v3f(p3f(cx+size, cy, cz));
endline();
/* Draw y-axis arm. */
bgnline();
v3f(p3f(cx, cy-size, cz));
v3f(p3f(cx, cy+size, cz));
endline();
/* Draw z-axis arm. */
bgnline();
v3f(p3f(cx, cy, cz-size));
v3f(p3f(cx, cy, cz+size));
endline();
}
/* AXES */
if (local_info.hereonly.value & (AXESSMALL|AXESLARGE))
draw_axes(state, win, obj, info, local_info.hereonly.value);
/* GRID */
if (local_info.hereonly.value & GRIDXY)
draw_grid(state, win, obj, info, GRIDXY);
if (local_info.hereonly.value & GRIDXZ)
draw_grid(state, win, obj, info, GRIDXZ);
if (local_info.hereonly.value & GRIDYZ)
draw_grid(state, win, obj, info, GRIDYZ);
/* SCATTER */
if (local_info.heredown.value & SCATXY)
draw_scatter(state, win, obj, local_info.draw_fn, info, SCATXY);
if (local_info.heredown.value & SCATXZ)
draw_scatter(state, win, obj, local_info.draw_fn, info, SCATXZ);
if (local_info.heredown.value & SCATYZ)
draw_scatter(state, win, obj, local_info.draw_fn, info, SCATYZ);
/* BOUNDING BOX */
/* Bounding box for the entire dataset over time. */
if (local_info.hereonly.value & (BOXWIRE | BOXSHADED))
draw_box_style(state, win, win->stats[0],
local_info.hereonly.value & (BOXWIRE | BOXSHADED));
if ((obj != NULL) && (OBJ_INFO(obj) != NULL) &&
(OBJ_PICKMODE(obj) == PICK_OBJECT))
draw_box_style(state, win, obj->stats[0], (BOXSELECTED | BOXWIRE));
/* Restore the transformation matrix. */
popattributes();
popmatrix();
return ST_OKAY;
}
/* update info copies the oldinfo record into the newinfo record, then */
/* updates newinfo fields with new information from the updinfo record. */
/* Only fields which have changed in updinfo are used. If no errors */
/* occur, the function returns ST_OKAY. */
int update_info(state_t *state, objinfo_t *oldinfo, objinfo_t *updinfo,
objinfo_t *newinfo)
{
/* At the very least, the new information is the same as the old. */
memcpy((void *) newinfo, (void *) oldinfo, (size_t) sizeof(objinfo_t));
/* If the update information pointer is NULL, no changes are being */
/* made. */
if (updinfo == NULL)
return ST_OKAY;
/* Update changed fields in the newinfo record from updinfo. */
if (updinfo->scl.used)
{
newinfo->scl.coord[X] = updinfo->scl.coord[X];
newinfo->scl.coord[Y] = updinfo->scl.coord[Y];
newinfo->scl.coord[Z] = updinfo->scl.coord[Z];
newinfo->scl.used = TRUE;
/* Add the scaling to the transformation matrix. */
scale(updinfo->scl.coord[X], updinfo->scl.coord[Y],
updinfo->scl.coord[Z]);
}
else
{
newinfo->scl.used = FALSE;
}
if (updinfo->rot.used)
{
newinfo->rot.coord[PHI] = updinfo->rot.coord[PHI];
newinfo->rot.coord[THETA] = updinfo->rot.coord[THETA];
newinfo->rot.used = TRUE;
/* Add the rotation to the transformation matrix. */
rot(updinfo->rot.coord[PHI], 'y');
rot(updinfo->rot.coord[THETA], 'z');
}
else
{
newinfo->rot.used = FALSE;
}
if (updinfo->trn.used)
{
newinfo->trn.coord[X] = updinfo->trn.coord[X];
newinfo->trn.coord[Y] = updinfo->trn.coord[Y];
newinfo->trn.coord[Z] = updinfo->trn.coord[Z];
newinfo->trn.used = TRUE;
translate(updinfo->trn.coord[X], updinfo->trn.coord[Y],
updinfo->trn.coord[Z]);
}
else
{
newinfo->trn.used = FALSE;
}
if (updinfo->draw_fn != NULL)
newinfo->draw_fn = updinfo->draw_fn;
else
newinfo->draw_fn = oldinfo->draw_fn;
/* Do something with ATPOINT, BOXWIRE, BOXSHADED, LABELS */
newinfo->hereonly = updinfo->hereonly;
newinfo->heredown.used = TRUE;
newinfo->heredown.value = updinfo->heredown.value | oldinfo->heredown.value;
return ST_OKAY;
}
int draw_nothing (state_t *state, window_t *win, object_t *obj,
objinfo_t *info)
{
if (OBJ_PICKMODE(obj) == PICK_FACE)
return DrawPickedFaces(state, win, obj, info);
else if (OBJ_PICKMODE(obj) == PICK_VERTEX)
return DrawPickedVertices(state, win, obj, info);
/* This is new. */
return ST_OKAY;
}
int draw_vertices(state_t *state, window_t *win, object_t *obj,
objinfo_t *info)
{
float jackscale;
long count;
Vdata_t **vdata;
Vdata_t *vcolor_v;
Vdata_t *pcoord_v;
float (*pcoord)[DIMS];
int *vcolor;
char *picked;
int single_color;
/* Get pointers to the pertinent data sets */
vdata = obj->u.obj.vdata;
vcolor_v = get_vdata(state, vdata[VCOLOR]);
if ((pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
return ST_OKAY;
/* Set up the consolidated coordinate array pointer. */
pcoord = (float (*)[DIMS]) pcoord_v->data;
count = pcoord_v->stats[0].rec_count;
assert (pcoord_v->stats[0].type == PVFLOAT);
/* Get a pointer to the pick list if the object is picked and it */
/* is in the proper mode. */
picked = OBJ_PICKLIST(obj);
if (OBJ_PICKMODE(obj) != PICK_VERTEX)
picked = NULL;
if (OBJ_PICKMODE(obj) == PICK_FACE)
DrawPickedFaces(state, win, obj, info);
if (FEQ(win->sphere_size, 0.0))
{
/* If there is no vertex color information, draw without it */
/* (use the FOREGROUND color). Otherwise, grab the color array. */
jackscale = win->max_width / 100.0;
if (vcolor_v == NULL || vcolor_v->data == NULL)
{
cpack(FOREGROUND);
/* No color information. Use foreground and draw the */
/* appropriate shapes. */
bgnpoint();
while (count > 0)
{
if (picked && *picked)
{ /* selected */
endpoint();
DrawJack(pcoord, jackscale);
bgnpoint();
}
else
{ /* not selected */
v3f(*pcoord);
if (!(count & 255))
{
endpoint();
bgnpoint();
}
}
/* Move to the next x, y, z set and decrement the */
/* count. */
if (picked)
picked++;
pcoord++;
count--;
}
endpoint();
}
else
{
/* Set pointers to the actual data and the size of the data */
/* sets. */
assert (vcolor_v->stats[0].type == PVINTEGER);
/* There is color information. Get it and use it to draw the */
/* appropriate shapes. */
vcolor = (int *) vcolor_v->data;
bgnpoint();
while (count > 0)
{
if (picked && *picked)
{ /* selected */
endpoint();
cpack(FOREGROUND);
DrawJack(pcoord, jackscale);
bgnpoint();
}
else
{ /* not selected */
PALETTECPACK(*vcolor);
v3f(*pcoord);
if (!(count & 255))
{
endpoint();
bgnpoint();
}
}
/* Move to the next x, y, z set, color entry, and */
/* decrement the count. */
if (picked)
picked++;
pcoord++;
vcolor++;
count--;
}
endpoint();
}
}
else
{
/* If there is no vertex color information, draw without it */
/* (use the FOREGROUND color). Otherwise, grab the color array. */
jackscale = win->max_width / 100.0;
/* Set sphere mode. */
sphmode (SPH_DEPTH, win->sphere_depth);
sphmode (SPH_TESS, SPH_CUBE);
/* Backfacing is safe since we're spheres. */
backface (TRUE);
/* Turn on lighting if appropriate. */
if (WIN_LIGHT(win))
lighting_on (state, win,
WIN_LIGHT_X(win), WIN_LIGHT_Y(win), WIN_LIGHT_Z(win));
if (vcolor_v == NULL || vcolor_v->data == NULL)
{
cpack(FOREGROUND);
/* No color information. Use foreground and draw the */
/* appropriate shapes. */
while (count > 0)
{
if (picked && *picked)
{ /* selected */
DrawJack(pcoord, jackscale);
}
else
{ /* not selected */
float params[4];
params[0] = (*pcoord)[0];
params[1] = (*pcoord)[1];
params[2] = (*pcoord)[2];
params[3] = win->sphere_size;
sphdraw (params);
}
/* Move to the next x, y, z set and decrement the */
/* count. */
if (picked) picked++;
pcoord++;
count--;
}
}
else
{
/* Set pointers to the actual data and the size of the data */
/* sets. */
assert (vcolor_v->stats[0].type == PVINTEGER);
/* There is color information. Get it and use it to draw the */
/* appropriate shapes. */
vcolor = (int *) vcolor_v->data;
/* Look to see if we've got a one-color palette. Right
now we look for the unlikely event that state->pal[69] =
state->pal[149] = state->pal[219]. */
if (state->pal[69][R] == state->pal[149][R] &&
state->pal[149][R] == state->pal[219][R] &&
state->pal[69][G] == state->pal[149][G] &&
state->pal[149][G] == state->pal[219][G] &&
state->pal[0][B] == state->pal[255][B] &&
state->pal[1][R] == state->pal[254][R] &&
state->pal[10][G] == state->pal[245][G])
{
single_color = 1;
PALETTECPACK(69);
}
else
single_color = 0;
while (count > 0)
{
if (picked && *picked)
{ /* selected */
cpack(FOREGROUND);
DrawJack(pcoord, jackscale);
if (single_color)
PALETTECPACK(69);
}
else
{ /* not selected */
float params[4];
if (!single_color)
PALETTECPACK(*vcolor);
params[0] = (*pcoord)[0];
params[1] = (*pcoord)[1];
params[2] = (*pcoord)[2];
params[3] = win->sphere_size;
sphdraw (params);
}
/* Move to the next x, y, z set, color entry, and */
/* decrement the count. */
if (picked) picked++;
pcoord++;
vcolor++;
count--;
}
}
/* Turn off lighting if it's on. */
if (WIN_LIGHT(win))
lighting_off ();
backface(FALSE);
}
return ST_OKAY;
}
int draw_edges (state_t *state, window_t *win, object_t *obj, objinfo_t *info)
{
long count;
Vdata_t **vdata, *vcolor_v, *pcoord_v, *connect_v;
float (*pcoord)[DIMS];
int *vcolor, *connect;
char *picked;
int i, nvert, vertex;
linewidth (win->line_width);
/* Get pointers to the pertinent data sets */
vdata = obj->u.obj.vdata;
vcolor_v = get_vdata(state, vdata[VCOLOR]);
if ((connect_v = get_vdata(state, vdata[CONNECT])) == NULL)
if ((connect_v = get_vdata(state, vdata[MCONNECT])) == NULL)
{
draw_vertices(state, win, obj, info);
return ST_OKAY;
}
if ((pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
return ST_OKAY;
/* Collect connectivity information for drawing. */
connect = (int *) connect_v->data;
count = connect_v->stats[0].rec_count;
nvert = connect_v->stats[0].rec_size;
/* Set up the consolidated coordinate array pointer. */
pcoord = (float (*)[DIMS]) pcoord_v->data;
assert (pcoord_v->stats[0].type == PVFLOAT);
/* Get a pointer to the pick list if the object is picked and it */
/* is in the proper mode. */
picked = OBJ_PICKLIST(obj);
if (OBJ_PICKMODE(obj) != PICK_FACE)
picked = NULL;
if (OBJ_PICKMODE(obj) == PICK_VERTEX)
DrawPickedVertices(state, win, obj, info);
/* If there is no vertex color information, draw without it */
/* (use the FOREGROUND color). Otherwise, grab the color array. */
if (vcolor_v == NULL || vcolor_v->data == NULL)
{
cpack(FOREGROUND);
/* No color information. Use foreground and draw the */
/* appropriate shapes. */
while (count > 0)
{
if (picked && *picked)
bgnpolygon();
else
bgnclosedline();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
v3f(pcoord[vertex]);
}
if (picked && *picked)
endpolygon();
else
endclosedline();
if (picked)
picked++;
count--;
}
}
else
{
/* Set pointers to the actual data and the size of the data */
/* sets. */
assert (vcolor_v->stats[0].type == PVINTEGER);
/* There is color information. Get it and use it to draw the */
/* appropriate shapes. */
vcolor = (int *) vcolor_v->data;
while (count > 0)
{
if (picked && *picked)
bgnpolygon();
else
bgnclosedline();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
PALETTECPACK(vcolor[vertex]);
v3f(pcoord[vertex]);
}
if (picked && *picked)
endpolygon();
else
endclosedline();
if (picked) picked++;
count--;
}
}
linewidth (1);
return ST_OKAY;
}
int DrawTrans (state_t *state, window_t *win, object_t *obj, objinfo_t *info)
{
/* Set the opacity level to one-half. */
SetOpacity(0.5);
/* Draw the object as faces. */
draw_faces(state, win, obj, info);
/* Restore objects to full-opacity. */
SetOpacity(1.0);
return ST_OKAY;
}
int draw_faces (state_t *state, window_t *win, object_t *obj, objinfo_t *info)
{
long count;
Vdata_t **vdata, *vcolor_v, *pcoord_v, *connect_v;
float (*pcoord)[DIMS];
int *vcolor, *connect;
char *picked;
int i, nvert, vertex, single_color;
/* Get pointers to the pertinent data sets */
vdata = obj->u.obj.vdata;
vcolor_v = get_vdata(state, vdata[VCOLOR]);
if ( (connect_v = get_vdata(state, vdata[CONNECT])) == NULL)
if ( (connect_v = get_vdata(state, vdata[MCONNECT])) == NULL)
return draw_vertices(state, win, obj, info);
/* If the plist does not describe polygons, draw edges. */
if (connect_v->stats[0].rec_size < 3)
return draw_edges(state, win, obj, info);
if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
return ST_OKAY;
/* Collect connectivity information for drawing. */
connect = (int *) connect_v->data;
count = connect_v->stats[0].rec_count;
nvert = connect_v->stats[0].rec_size;
/* Set up the consolidated coordinate array pointer. */
pcoord = (float (*)[DIMS]) pcoord_v->data;
assert (pcoord_v->stats[0].type == PVFLOAT);
/* Get a pointer to the pick list if the object is picked and it */
/* is in the proper mode. */
picked = OBJ_PICKLIST(obj);
if (OBJ_PICKMODE(obj) != PICK_FACE)
picked = NULL;
if (OBJ_PICKMODE(obj) == PICK_VERTEX)
DrawPickedVertices(state, win, obj, info);
/* If there is no vertex color information, draw without it */
/* (use the FOREGROUND color). Otherwise, grab the color array. */
/* Turn on lighting if appropriate. */
if (WIN_LIGHT(win))
lighting_on (state, win,
WIN_LIGHT_X(win), WIN_LIGHT_Y(win), WIN_LIGHT_Z(win));
if (vcolor_v == NULL || vcolor_v->data == NULL)
{
cpack(FOREGROUND);
/* No color information. Use foreground and draw the */
/* appropriate shapes. */
while (count > 0)
{
/* If lighting is on, find a normal for the polygon. */
if (WIN_LIGHT(win))
{
find_normal(pcoord[*(connect)-1], pcoord[*(connect+1)-1],
pcoord[*(connect+2)-1]);
n3f (nn);
}
bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
v3f(pcoord[vertex]);
}
endpolygon();
if (picked)
picked++;
count--;
}
}
else
{
/* Set pointers to the actual data and the size of the data */
/* sets. */
assert (vcolor_v->stats[0].type == PVINTEGER);
/* There is color information. Get it and use it to draw the */
/* appropriate shapes. */
vcolor = (int *) vcolor_v->data;
/* Look to see if we've got a one-color palette. Right
now we look for the unlikely event that pal[69] =
pal[149] = pal[219]. */
if (state->pal[69][R] == state->pal[149][R] &&
state->pal[149][R] == state->pal[219][R] &&
state->pal[69][G] == state->pal[149][G] &&
state->pal[149][G] == state->pal[219][G] &&
state->pal[0][B] == state->pal[255][B] &&
state->pal[1][R] == state->pal[254][R] &&
state->pal[10][G] == state->pal[245][G])
{
single_color = 1;
PALETTECPACK(69);
}
else
single_color = 0;
while (count > 0)
{
/* If lighting is on, find a normal for the polygon. */
if (WIN_LIGHT(win))
{
find_normal(pcoord[*(connect)-1], pcoord[*(connect+1)-1],
pcoord[*(connect+2)-1]);
n3f (nn);
}
bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ((vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
if (picked && *picked)
cpack(FOREGROUND);
else
{
if (!single_color)
PALETTECPACK(vcolor[vertex]);
}
v3f(pcoord[vertex]);
if (single_color && picked && *picked)
PALETTECPACK(69);
}
endpolygon();
if (picked) picked++;
count--;
}
}
/* Turn off lighting if it's on. */
if (WIN_LIGHT(win))
lighting_off ();
return ST_OKAY;
}
int draw_outlined_faces(state_t *state, window_t *win, object_t *obj,
objinfo_t *info)
{
long count;
Vdata_t **vdata, *vcolor_v, *pcoord_v, *connect_v;
float (*pcoord)[DIMS];
float pcoord_outline[DIMS];
int *vcolor, *connect, *oconnect;
char *picked;
int i, j, nvert, vertex, single_color;
/* Get pointers to the pertinent data sets */
vdata = obj->u.obj.vdata;
vcolor_v = get_vdata(state, vdata[VCOLOR]);
if ( (connect_v = get_vdata(state, vdata[CONNECT])) == NULL)
if ( (connect_v = get_vdata(state, vdata[MCONNECT])) == NULL)
return draw_vertices(state, win, obj, info);
/* If the plist does not describe polygons, draw edges. */
if (connect_v->stats[0].rec_size < 3)
return draw_edges(state, win, obj, info);
if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
return ST_OKAY;
/* Collect connectivity information for drawing. */
oconnect = connect = (int *) connect_v->data;
count = connect_v->stats[0].rec_count;
nvert = connect_v->stats[0].rec_size;
/* Set up the consolidated coordinate array pointer. */
pcoord = (float (*)[DIMS]) pcoord_v->data;
assert (pcoord_v->stats[0].type == PVFLOAT);
/* Get a pointer to the pick list if the object is picked and it */
/* is in the proper mode. */
picked = OBJ_PICKLIST(obj);
if (OBJ_PICKMODE(obj) != PICK_FACE)
picked = NULL;
if (OBJ_PICKMODE(obj) == PICK_VERTEX)
DrawPickedVertices(state, win, obj, info);
linewidth(win->line_width);
/* Set up the squeezed zbuffer. */
grok_squeezed_zbuffer (state, win);
/* If there is no vertex color information, draw without it. */
/* Otherwise, grab the color array. */
if (vcolor_v == NULL || vcolor_v->data == NULL)
{
/* Turn on lighting if appropriate. */
if (WIN_LIGHT(win))
lighting_on (state, win,
WIN_LIGHT_X(win), WIN_LIGHT_Y(win), WIN_LIGHT_Z(win));
while (count > 0)
{
/* Set one normal for the whole damn thing. */
if (WIN_LIGHT(win))
{
find_normal(pcoord[*(connect)-1],
pcoord[*(connect+1)-1], pcoord[*(connect+2)-1]);
n3f (nn);
}
if (picked && *picked)
{
cpack(FOREGROUND);
bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
v3f(pcoord[vertex]);
}
endpolygon();
}
else
{
/* Save connectivity pointer. */
oconnect = connect;
/* Draw the polygon. */
cpack (0xffffff);
bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
v3f(pcoord[vertex]);
}
endpolygon();
/* Start connectivity anew. */
connect = oconnect;
/* Squeeze the zbuffer. */
set_squeezed_zbuffer ();
/* Draw the outline of the polygon, with Z values */
cpack(WIN_OUTLINE_COLOR(win));
bgnclosedline();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
v3f(pcoord[vertex]);
}
endclosedline();
/* Restore the Zbuffer. */
lsetdepth (gstate->zmax, gstate->zmin);
}
if (picked) picked++;
count--;
}
/* Turn off lighting if it's on. */
if (WIN_LIGHT(win))
lighting_off ();
}
else
{
/* Set pointers to the actual data and the size of the data */
/* sets. */
assert (vcolor_v->stats[0].type == PVINTEGER);
/* There is color information. Get it and use it to draw the */
/* appropriate shapes. */
vcolor = (int *) vcolor_v->data;
/* Turn on lighting if appropriate. */
if (WIN_LIGHT(win))
lighting_on (state, win,
WIN_LIGHT_X(win), WIN_LIGHT_Y(win), WIN_LIGHT_Z(win));
while (count > 0)
{
/* Set one normal for the whole damn thing. */
if (WIN_LIGHT(win))
{
find_normal(pcoord[*(connect)-1],
pcoord[*(connect+1)-1], pcoord[*(connect+2)-1]);
n3f (nn);
}
if (picked && *picked)
{
bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
PALETTECPACK(vcolor[vertex]);
v3f(pcoord[vertex]);
}
endpolygon();
}
else
{
/* Save connectivity pointer. */
oconnect = connect;
/* Draw the polygon. */
bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
PALETTECPACK(vcolor[vertex]);
v3f(pcoord[vertex]);
}
endpolygon();
/* Start connectivity anew. */
connect = oconnect;
/* Squeeze the zbuffer. */
set_squeezed_zbuffer ();
/* Draw the outline of the polygon, with Z values */
cpack(WIN_OUTLINE_COLOR(win));
bgnclosedline();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
v3f(pcoord[vertex]);
}
endclosedline();
/* Restore the Zbuffer. */
lsetdepth (gstate->zmax, gstate->zmin);
}
if (picked) picked++;
count--;
}
/* Turn off lighting if it's on. */
if (WIN_LIGHT(win))
lighting_off ();
}
linewidth (1);
return ST_OKAY;
}
int draw_hidden_edges(state_t *state, window_t *win, object_t *obj,
objinfo_t *info)
{
long count;
Vdata_t **vdata, *vcolor_v, *pcoord_v, *connect_v;
float (*pcoord)[DIMS];
float pcoord_outline[DIMS];
int *vcolor, *connect, *oconnect;
char *picked;
int i, j, nvert, vertex, single_color;
/* Get pointers to the pertinent data sets */
vdata = obj->u.obj.vdata;
vcolor_v = get_vdata(state, vdata[VCOLOR]);
if ( (connect_v = get_vdata(state, vdata[CONNECT])) == NULL)
if ( (connect_v = get_vdata(state, vdata[MCONNECT])) == NULL)
return draw_vertices(state, win, obj, info);
/* If the plist does not describe polygons, draw edges. */
if (connect_v->stats[0].rec_size < 3)
return draw_edges(state, win, obj, info);
if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
return ST_OKAY;
/* Collect connectivity information for drawing. */
oconnect = connect = (int *) connect_v->data;
count = connect_v->stats[0].rec_count;
nvert = connect_v->stats[0].rec_size;
/* Set up the consolidated coordinate array pointer. */
pcoord = (float (*)[DIMS]) pcoord_v->data;
assert (pcoord_v->stats[0].type == PVFLOAT);
/* Get a pointer to the pick list if the object is picked and it */
/* is in the proper mode. */
picked = OBJ_PICKLIST(obj);
if (OBJ_PICKMODE(obj) != PICK_FACE)
picked = NULL;
if (OBJ_PICKMODE(obj) == PICK_VERTEX)
DrawPickedVertices(state, win, obj, info);
linewidth(win->line_width);
/* Set up the squeezed zbuffer. */
grok_squeezed_zbuffer (state, win);
/* If there is no vertex color information, draw without it. */
/* Otherwise, grab the color array. */
if (vcolor_v == NULL || vcolor_v->data == NULL)
{
while (count > 0)
{
if (picked && *picked)
{
cpack(FOREGROUND);
bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
v3f(pcoord[vertex]);
}
endpolygon();
}
else
{
/* Save connectivity pointer. */
oconnect = connect;
/* Draw the polygon. */
cpack (0);
bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
v3f(pcoord[vertex]);
}
endpolygon();
/* Start connectivity anew. */
connect = oconnect;
/* Squeeze the zbuffer. */
set_squeezed_zbuffer ();
/* Draw the outline of the polygon, with Z values */
cpack (FOREGROUND);
bgnclosedline();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
v3f(pcoord[vertex]);
}
endclosedline();
/* Restore the Zbuffer. */
lsetdepth (gstate->zmax, gstate->zmin);
}
if (picked) picked++;
count--;
}
}
else
{
/* Set pointers to the actual data and the size of the data */
/* sets. */
assert (vcolor_v->stats[0].type == PVINTEGER);
/* There is color information. Get it and use it to draw the */
/* appropriate shapes. */
vcolor = (int *) vcolor_v->data;
while (count > 0)
{
if (picked && *picked)
{
bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
PALETTECPACK(vcolor[vertex]);
v3f(pcoord[vertex]);
}
endpolygon();
}
else
{
/* Save connectivity pointer. */
oconnect = connect;
/* Draw the polygon. */
cpack (0);
bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
v3f(pcoord[vertex]);
}
endpolygon();
/* Start connectivity anew. */
connect = oconnect;
/* Squeeze the zbuffer. */
set_squeezed_zbuffer ();
/* Draw the outline of the polygon, with Z values */
bgnclosedline();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
PALETTECPACK(vcolor[vertex]);
v3f(pcoord[vertex]);
}
endclosedline();
/* Restore the Zbuffer. */
lsetdepth (gstate->zmax, gstate->zmin);
}
if (picked) picked++;
count--;
}
}
linewidth (1);
return ST_OKAY;
}
/* DRAW PICKED ELEMENTS */
int DrawPickedVertices(state_t *state, window_t *win, object_t *obj,
objinfo_t *info)
{
float jackscale;
long count;
Vdata_t **vdata;
Vdata_t *pcoord_v;
float (*pcoord)[DIMS];
char *picked;
/* Get pointers to the pertinent data sets */
vdata = obj->u.obj.vdata;
if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
return ST_OKAY;
/* Set up the consolidated coordinate array pointer. */
pcoord = (float (*)[DIMS]) pcoord_v->data;
count = pcoord_v->stats[0].rec_count;
assert (pcoord_v->stats[0].type == PVFLOAT);
/* Get a pointer to the pick list if the object is picked and it */
/* is in the proper mode. */
picked = OBJ_PICKLIST(obj);
if (OBJ_PICKMODE(obj) != PICK_VERTEX)
return ST_ERROR;
jackscale = win->max_width / 100.0;
/* No color information. Use foreground and draw the */
/* appropriate shapes. */
cpack(FOREGROUND);
while (count > 0)
{
if (*picked)
DrawJack(pcoord, jackscale);
/* Move to the next x, y, z set and decrement the */
/* count. */
picked++;
pcoord++;
count--;
}
return ST_OKAY;
}
int DrawPickedFaces (state_t *state, window_t *win, object_t *obj,
objinfo_t *info)
{
long count;
Vdata_t **vdata;
Vdata_t *vcolor_v;
Vdata_t *pcoord_v;
Vdata_t *connect_v;
float (*pcoord)[DIMS];
int *vcolor;
int *connect;
char *picked;
int i, nvert, vertex;
/* Get pointers to the pertinent data sets */
vdata = obj->u.obj.vdata;
vcolor_v = get_vdata(state, vdata[VCOLOR]);
if ( (connect_v = get_vdata(state, vdata[CONNECT])) == NULL)
if ( (connect_v = get_vdata(state, vdata[MCONNECT])) == NULL)
return draw_vertices(state, win, obj, info);
/* If the plist does not describe polygons, draw edges. */
if (connect_v->stats[0].rec_size < 3)
return draw_edges(state, win, obj, info);
if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
return ST_OKAY;
/* Collect connectivity information for drawing. */
connect = (int *) connect_v->data;
count = connect_v->stats[0].rec_count;
nvert = connect_v->stats[0].rec_size;
/* Set up the consolidated coordinate array pointer. */
pcoord = (float (*)[DIMS]) pcoord_v->data;
assert (pcoord_v->stats[0].type == PVFLOAT);
/* Get a pointer to the pick list if the object is picked and it */
/* is in the proper mode. */
picked = OBJ_PICKLIST(obj);
if (OBJ_PICKMODE(obj) != PICK_FACE)
return ST_ERROR;
/* If there is no vertex color information, draw without it */
/* (use the FOREGROUND color). Otherwise, grab the color array. */
if (vcolor_v == NULL || vcolor_v->data == NULL)
{
/* No color information. Use foreground and draw the */
/* appropriate shapes. */
color(FOREGROUND);
while (count > 0)
{
if (*picked)
{
bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
v3f(pcoord[vertex]);
}
endpolygon();
}
else
{
connect += nvert;
}
if (picked)
picked++;
count--;
}
}
else
{
/* Set pointers to the actual data and the size of the data */
/* sets. */
assert (vcolor_v->stats[0].type == PVINTEGER);
/* There is color information. Get it and use it to draw the */
/* appropriate shapes. */
vcolor = (int *) vcolor_v->data;
while (count > 0)
{
if (*picked)
{
bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
PALETTECPACK(vcolor[vertex]);
v3f(pcoord[vertex]);
}
endpolygon();
}
else
{
connect += nvert;
}
if (picked)
picked++;
count--;
}
}
return ST_OKAY;
}
/* ------------------------------------------------------------------------ */
/* ----------------------- RAYSHADE OUTPUT ROUTINES ----------------------- */
/* ------------------------------------------------------------------------ */
static FILE *rayfp = NULL;
static void ray_bgnpolygon (void)
{
fprintf (rayfp, " poly \n");
return;
}
static void ray_v3f (float *vv)
{
fprintf (rayfp, " %f %f %f\n", vv[0], vv[1], vv[2]);
return;
}
static void ray_endpolygon (void)
{
return;
}
static void ray_palettecpack (int c)
{
fprintf (rayfp, " pal%1d\n", c);
return;
}
/* Keep a static array of vertices and a count of the number
of vertices in the array. */
static float line_vv[20][3];
static int line_vv_count = 0;
static int line_cc[20];
static int line_cc_used = 0;
/* Static width of lines drawn as cylinders. */
static float line_width = 0.1;
/* This should be a window-local variable or something. */
static int cap_cylinders = 0;
static void ray_linepalettecpack (int c)
{
/* Save this color index with the current vertex. */
line_cc[line_vv_count] = c;
/* Note that we are using colors for this line. */
line_cc_used = 1;
}
static void ray_bgnclosedline (void)
{
/* Starting a new line. */
line_vv_count = 0;
/* Haven't used any colors yet. */
line_cc_used = 0;
}
static void ray_endclosedline (void)
{
int i;
/* If we have one or fewer vertices, punt. */
if (line_vv_count < 2)
goto done;
/* For each vertex up to the second-to-last, make
a cylinder with the vertex and its successor. */
for (i = 0; i < line_vv_count - 1; i++)
{
fprintf (rayfp, " cylinder\n");
if (line_cc_used)
{
/* We've used colors, so set a color. */
fprintf (rayfp, " pal%1d\n", line_cc[i]);
}
fprintf (rayfp, " %s\n %f %f %f\n %f %f %f\n",
/* radius */ "CYL_RAD",
/* end 1 */ line_vv[i][0], line_vv[i][1], line_vv[i][2],
/* end 2 */ line_vv[i+1][0], line_vv[i+1][1], line_vv[i+1][2]);
if (cap_cylinders)
{
fprintf (rayfp, " disc\n");
if (line_cc_used)
fprintf (rayfp, " pal%1d\n", line_cc[i]);
fprintf (rayfp, " %s\n %f %f %f\n %f %f %f\n",
"CYL_RAD",
line_vv[i][0], line_vv[i][1], line_vv[i][2],
line_vv[i][0] - line_vv[i+1][0],
line_vv[i][1] - line_vv[i+1][1],
line_vv[i][2] - line_vv[i+1][2]);
fprintf (rayfp, " disc\n");
if (line_cc_used)
fprintf (rayfp, " pal%1d\n", line_cc[i]);
fprintf (rayfp, " %s\n %f %f %f\n %f %f %f\n",
"CYL_RAD",
line_vv[i+1][0], line_vv[i+1][1], line_vv[i+1][2],
line_vv[i+1][0] - line_vv[i][0],
line_vv[i+1][1] - line_vv[i][1],
line_vv[i+1][2] - line_vv[i][2]);
}
}
/* If there's more than 2 vertices, close the line. */
if (line_vv_count > 2)
{
i = line_vv_count - 1;
fprintf (rayfp, " cylinder\n");
if (line_cc_used)
{
fprintf (rayfp, " pal%1d\n", line_cc[i]);
}
fprintf (rayfp, " %s\n %f %f %f\n %f %f %f\n",
/* radius */ "CYL_RAD",
/* end 1 */ line_vv[i][0], line_vv[i][1], line_vv[i][2],
/* end 2 */ line_vv[0][0], line_vv[0][1], line_vv[0][2]);
if (cap_cylinders)
{
fprintf (rayfp, " disc\n");
if (line_cc_used)
fprintf (rayfp, " pal%1d\n", line_cc[i]);
fprintf (rayfp, " %s\n %f %f %f\n %f %f %f\n",
"CYL_RAD",
line_vv[i][0], line_vv[i][1], line_vv[i][2],
line_vv[i][0] - line_vv[0][0],
line_vv[i][1] - line_vv[0][1],
line_vv[i][2] - line_vv[0][2]);
fprintf (rayfp, " disc\n");
if (line_cc_used)
fprintf (rayfp, " pal%1d\n", line_cc[i]);
fprintf (rayfp, " %s\n %f %f %f\n %f %f %f\n",
"CYL_RAD",
line_vv[0][0], line_vv[0][1], line_vv[0][2],
line_vv[0][0] - line_vv[i][0],
line_vv[0][1] - line_vv[i][1],
line_vv[0][2] - line_vv[i][2]);
}
}
done:
line_vv_count = 0;
return;
}
static void ray_linev3f (float *vv)
{
/* Store this vertex. */
line_vv[line_vv_count][0] = vv[0];
line_vv[line_vv_count][1] = vv[1];
line_vv[line_vv_count][2] = vv[2];
/* Increment the count. */
line_vv_count++;
return;
}
/* ------------------------------------------------------------------------ */
/* ------------------------ SPHERE RAY/GL ROUTINES ------------------------ */
/* ------------------------------------------------------------------------ */
static float sphere_size;
/* 1 if vertices should be drawn as cubes. */
static int sphere_cubes;
static int sphere_col_set = 0;
static int sphere_col;
static void ray_sphpalettecpack (int c)
{
sphere_col_set = 1;
sphere_col = c;
return;
}
static void ray_sphdraw (float *vv)
{
if (sphere_cubes)
{
fprintf (rayfp, " box\n");
if (sphere_col_set)
fprintf (rayfp, " pal%1d\n", sphere_col);
fprintf (rayfp, " (%f-SPH_RAD) (%f-SPH_RAD) (%f-SPH_RAD)\n",
vv[0],
vv[1],
vv[2]);
fprintf (rayfp, " (%f+SPH_RAD) (%f+SPH_RAD) (%f+SPH_RAD)\n",
vv[0],
vv[1],
vv[2]);
}
else
{
fprintf (rayfp, " sphere\n");
if (sphere_col_set)
fprintf (rayfp, " pal%1d\n", sphere_col);
fprintf (rayfp, " %s\n", "SPH_RAD");
fprintf (rayfp, " %f %f %f\n", vv[0], vv[1], vv[2]);
}
/* Make sure we don't repeat a color. */
sphere_col_set = 0;
return;
}
static int ray_draw_vertices (state_t *state, window_t *win, object_t *obj,
objinfo_t *info)
{
long count;
Vdata_t **vdata;
Vdata_t *vcolor_v;
Vdata_t *pcoord_v;
float (*pcoord)[DIMS];
int *vcolor;
char *picked;
int single_color;
/* Get pointers to the pertinent data sets */
vdata = obj->u.obj.vdata;
vcolor_v = get_vdata(state, vdata[VCOLOR]);
if ((pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
return ST_OKAY;
/* Set up the consolidated coordinate array pointer. */
pcoord = (float (*)[DIMS]) pcoord_v->data;
count = pcoord_v->stats[0].rec_count;
assert (pcoord_v->stats[0].type == PVFLOAT);
if (FEQ(win->sphere_size, 0.0))
sphere_size = win->max_width * 0.01;
else
sphere_size = win->sphere_size;
fprintf (rayfp, "#define SPH_RAD %f\n", sphere_size);
sphere_cubes = (win->sphere_depth == 1);
if (vcolor_v == NULL || vcolor_v->data == NULL)
{
/* No color information. Use foreground and draw the */
/* appropriate shapes. */
while (count > 0)
{
{ /* not selected */
float params[4];
params[0] = (*pcoord)[0];
params[1] = (*pcoord)[1];
params[2] = (*pcoord)[2];
params[3] = win->sphere_size;
ray_sphdraw (params);
}
/* Move to the next x, y, z set and decrement the */
/* count. */
pcoord++;
count--;
}
}
else
{
/* Set pointers to the actual data and the size of the data */
/* sets. */
assert (vcolor_v->stats[0].type == PVINTEGER);
/* There is color information. Get it and use it to draw the */
/* appropriate shapes. */
vcolor = (int *) vcolor_v->data;
while (count > 0)
{
{ /* not selected */
float params[4];
ray_sphpalettecpack(*vcolor);
params[0] = (*pcoord)[0];
params[1] = (*pcoord)[1];
params[2] = (*pcoord)[2];
params[3] = win->sphere_size;
ray_sphdraw (params);
}
/* Move to the next x, y, z set, color entry, and */
/* decrement the count. */
pcoord++;
vcolor++;
count--;
}
}
return ST_OKAY;
}
static int ray_draw_edges (state_t *state, window_t *win, object_t *obj,
objinfo_t *info)
{
long count;
Vdata_t **vdata, *vcolor_v, *pcoord_v, *connect_v;
float (*pcoord)[DIMS];
int *vcolor, *connect;
char *picked;
int i, nvert, vertex;
/* Set the width of the cylinders. */
line_width = WIN_MAXWIDTH(win) * 0.0005 * (float)(win->line_width);
fprintf (rayfp, "#define CYL_RAD %f\n", line_width);
/* Get pointers to the pertinent data sets. */
vdata = obj->u.obj.vdata;
vcolor_v = get_vdata(state, vdata[VCOLOR]);
if ((connect_v = get_vdata(state, vdata[CONNECT])) == NULL)
if ((connect_v = get_vdata(state, vdata[MCONNECT])) == NULL)
{
ray_draw_vertices(state, win, obj, info);
return ST_OKAY;
}
if ((pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
return ST_OKAY;
/* Collect connectivity information for drawing. */
connect = (int *) connect_v->data;
count = connect_v->stats[0].rec_count;
nvert = connect_v->stats[0].rec_size;
/* Set up the consolidated coordinate array pointer. */
pcoord = (float (*)[DIMS]) pcoord_v->data;
assert (pcoord_v->stats[0].type == PVFLOAT);
/* If there is no vertex color information, draw without it */
/* (use the FOREGROUND color). Otherwise, grab the color array. */
if (vcolor_v == NULL || vcolor_v->data == NULL)
{
/* No color information. Use foreground and draw the */
/* appropriate shapes. */
while (count > 0)
{
ray_bgnclosedline();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
ray_linev3f(pcoord[vertex]);
}
ray_endclosedline();
count--;
}
}
else
{
/* Set pointers to the actual data and the size of the data */
/* sets. */
assert (vcolor_v->stats[0].type == PVINTEGER);
/* There is color information. Get it and use it to draw the */
/* appropriate shapes. */
vcolor = (int *) vcolor_v->data;
while (count > 0)
{
ray_bgnclosedline();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
ray_linepalettecpack(vcolor[vertex]);
ray_linev3f(pcoord[vertex]);
}
ray_endclosedline();
count--;
}
}
return ST_OKAY;
}
static int ray_draw_faces (state_t *state, window_t *win, object_t *obj,
objinfo_t *info)
{
long count;
Vdata_t **vdata, *vcolor_v, *pcoord_v, *connect_v;
float (*pcoord)[DIMS];
int *vcolor, *connect;
char *picked;
int i, nvert, vertex, single_color;
/* Get pointers to the pertinent data sets */
vdata = obj->u.obj.vdata;
vcolor_v = get_vdata(state, vdata[VCOLOR]);
if ( (connect_v = get_vdata(state, vdata[CONNECT])) == NULL)
if ( (connect_v = get_vdata(state, vdata[MCONNECT])) == NULL)
return ray_draw_vertices(state, win, obj, info);
/* If the plist does not describe polygons, draw edges. */
if (connect_v->stats[0].rec_size < 3)
return ray_draw_edges(state, win, obj, info);
if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
return ST_OKAY;
/* Collect connectivity information for drawing. */
connect = (int *) connect_v->data;
count = connect_v->stats[0].rec_count;
nvert = connect_v->stats[0].rec_size;
/* Set up the consolidated coordinate array pointer. */
pcoord = (float (*)[DIMS]) pcoord_v->data;
assert (pcoord_v->stats[0].type == PVFLOAT);
/* If there is no vertex color information, draw without it */
/* (use the FOREGROUND color). Otherwise, grab the color array. */
if (vcolor_v == NULL || vcolor_v->data == NULL)
{
while (count > 0)
{
ray_bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
ray_v3f(pcoord[vertex]);
}
ray_endpolygon();
count--;
}
}
else
{
/* Set pointers to the actual data and the size of the data */
/* sets. */
assert (vcolor_v->stats[0].type == PVINTEGER);
/* There is color information. Get it and use it to draw the */
/* appropriate shapes. */
vcolor = (int *) vcolor_v->data;
while (count > 0)
{
ray_bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ((vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
if (i == nvert)
ray_palettecpack (vcolor[vertex]);
ray_v3f(pcoord[vertex]);
}
ray_endpolygon();
count--;
}
}
return ST_OKAY;
}
static int ray_draw_outlined_faces(state_t *state, window_t *win,
object_t *obj,
objinfo_t *info)
{
long count;
Vdata_t **vdata, *vcolor_v, *pcoord_v, *connect_v;
float (*pcoord)[DIMS];
float pcoord_outline[DIMS];
int *vcolor, *connect, *oconnect;
char *picked;
int i, j, nvert, vertex, single_color;
/* Set the width of the cylinders. */
line_width = WIN_MAXWIDTH(win) * 0.0005 * (float)(win->line_width);
fprintf (rayfp, "#define CYL_RAD %f\n", line_width);
/* Get pointers to the pertinent data sets */
vdata = obj->u.obj.vdata;
vcolor_v = get_vdata(state, vdata[VCOLOR]);
if ( (connect_v = get_vdata(state, vdata[CONNECT])) == NULL)
if ( (connect_v = get_vdata(state, vdata[MCONNECT])) == NULL)
return ray_draw_vertices(state, win, obj, info);
/* If the plist does not describe polygons, draw edges. */
if (connect_v->stats[0].rec_size < 3)
return ray_draw_edges(state, win, obj, info);
if ( (pcoord_v = get_vdata(state, vdata[PCOORD])) == NULL)
return ST_OKAY;
/* Collect connectivity information for drawing. */
oconnect = connect = (int *) connect_v->data;
count = connect_v->stats[0].rec_count;
nvert = connect_v->stats[0].rec_size;
/* Set up the consolidated coordinate array pointer. */
pcoord = (float (*)[DIMS]) pcoord_v->data;
assert (pcoord_v->stats[0].type == PVFLOAT);
/* If there is no vertex color information, draw without it. */
/* Otherwise, grab the color array. */
if (vcolor_v == NULL || vcolor_v->data == NULL)
{
while (count > 0)
{
/* Save connectivity pointer. */
oconnect = connect;
/* Draw the polygon. */
ray_bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
ray_v3f(pcoord[vertex]);
}
ray_endpolygon();
/* Start connectivity anew. */
connect = oconnect;
/* Draw the outline of the polygon, with Z values */
ray_bgnclosedline();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
ray_linev3f(pcoord[vertex]);
}
ray_endclosedline();
count--;
}
}
else
{
/* Set pointers to the actual data and the size of the data */
/* sets. */
assert (vcolor_v->stats[0].type == PVINTEGER);
/* There is color information. Get it and use it to draw the */
/* appropriate shapes. */
vcolor = (int *) vcolor_v->data;
while (count > 0)
{
/* Save connectivity pointer. */
oconnect = connect;
/* Draw the polygon. */
ray_bgnpolygon();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
if (i == nvert)
ray_palettecpack(vcolor[vertex]);
ray_v3f(pcoord[vertex]);
}
ray_endpolygon();
/* Start connectivity anew. */
connect = oconnect;
/* Draw the outline of the polygon, with Z values */
ray_bgnclosedline();
for (i = nvert; i > 0; i--)
{
if ( (vertex = *(connect++)-1) == -1)
{
connect += i-1;
break;
}
ray_linev3f(pcoord[vertex]);
}
ray_endclosedline();
count--;
}
}
return ST_OKAY;
}